﻿/*
 * @author: wizardc
 */

using System;
using System.Runtime.InteropServices;
using Unity.Jobs;

namespace Dou.Job
{
    /// <summary>
    /// 可使用托管数据的 IJobParallelFor
    /// 实现了 IJobParallelFor 的结构体，其属性都必须是结构体不能是类，使用该类可以突破这个限制
    /// </summary>
    /// <example>
    /// 
    /// [BurstCompile]
    /// unsafe class ExampleJob : ManagedJobParallelFor<ExampleJob>.IWork
    /// {
    ///     public Camera camera; // 可以定义任意类型
    /// 
    ///     [BurstCompile]
    ///     [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
    ///     [Il2CppSetOption(Option.NullChecks, false)]
    ///     public unsafe void Execute()
    ///     {
    ///         // 这里执行逻辑
    ///     }
    /// }
    /// 
    /// var exampleJob = new ExampleJob();
    /// exampleJob.xxx = xxx; // 这里可以赋值任意类型
    /// var job = new ManagedJobParallelFor<ExampleJob>();
    /// job.Work = exampleJob;
    /// var handle = job.Schedule(100000, 64);
    /// handle.Complete();
    /// job.Dispose();
    /// 
    /// </example>
    public struct ManagedJobParallelFor<T> : IJobParallelFor, IDisposable where T : class, ManagedJobParallelFor<T>.IWork
    {
        public interface IWork
        {
            void Execute(int index);
        }

        GCHandle _handle;

        private bool _initialized;

        public T Work
        {
            set
            {
                _handle = GCHandle.Alloc(value);
                _initialized = true;
            }
            get
            {
                return (T) _handle.Target;
            }
        }

        void IJobParallelFor.Execute(int index)
        {
            IWork task = (IWork) _handle.Target;
            task.Execute(index);
        }

        public void Dispose()
        {
            if (_initialized)
            {
                _handle.Free();
            }
            _initialized = false;
        }
    }
}
